package com.cwj.stream;

import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * @author chenwujie
 */
public class StreamTest {
    public static void main(String[] args) {
        // 1.
        Stream<Integer> integerStream = Stream.of(1, 2, 3, 4);

        // 2.
        Stream<Integer> build = Stream.<Integer>builder().add(1).add(2).add(3).add(4).build();

        // 3. 空对象
        Stream<Object> empty = Stream.empty();

        // 4. 对象生成器
        Stream<Integer> generate = Stream.generate(() -> ThreadLocalRandom.current().nextInt(10));
        Stream<Integer> iterate = Stream.iterate(100, x -> 1 + x);

        // 5. 数值类型区间
        //      [1, 10)
        IntStream range = IntStream.range(1, 10);
        //      [1, 10]
        IntStream intStream = IntStream.rangeClosed(1, 10);

        // 6.
        IntStream stream = Arrays.stream(new int[]{1, 2, 3});

        // 7. Collection
        Collection<String> collection = new ArrayList<>();
        Stream<String> stream1 = collection.stream();

        // 8. Files
        try {
            Stream<String> lines = Files.lines(Paths.get("test.txt"), StandardCharsets.UTF_8);
        } catch (IOException e) {
            e.printStackTrace();
        }

        // intermediate 中间操作



        // 1. distinct 去重
        Stream<Integer> integerStream1 = Stream.of(1, 2, 3, 3, 4);
        integerStream1.distinct().forEach(System.out::println);

        // 2. filter 过滤 返回满足过滤条件的元素流
        integerStream1.filter(e -> e > 2).forEach(System.out::println);

        // 3. limit 限制个数
        integerStream1.limit(2).forEach(System.out::println);

        // 4. map 映射，对每个元素进行处理，例如运算，增强，类型转换等
        integerStream1.map(String::valueOf).forEach(System.out::println);

        // 5. skip 丢弃前面的元素
        integerStream1.skip(1).forEach(System.out::println);

        // 6. peek 对流中元素进行一个操作，但是并不改变操作前的样子。
        integerStream1.peek(e -> System.out.println(e + 2)).forEach(System.out::println);

        // 7. sorted 排序
        integerStream1.sorted();

        // 8. flat 扁平化
        Stream.of(1, 2, 3, 4).flatMap(e -> Stream.of(e, e * 2, e * e)).map(i -> i * 10).forEach(System.out::println);


        // Terminal 终端操作(不再返回Stream)

        // 1. match
        Stream<Integer> stream2 = Stream.of(1, 2, 3, 4, 5);
        boolean b = stream2.allMatch(e -> e < 10);
        // or
        boolean b1 = stream2.anyMatch(e -> e == 3);
        boolean b2 = stream2.noneMatch(e -> e > 10);

        // 2. find
        Optional<Integer> first = stream2.findFirst();
        Optional<Integer> any = stream2.findAny();

        // 3. foreach
        stream2.forEach(System.out::println);
        stream2.forEachOrdered(System.out::println);

        // 4. count 元素个数
        long count = stream2.count();

        // 5. max 最大
        stream2.max(Comparator.comparingInt(e -> e));

        // 6. min 最小
        stream2.min(Comparator.comparingInt(e -> e));

        // 7. collect 聚合操作
        List<Integer> collect = stream2.collect(Collectors.toList());

        // 8. reduce(T , ) 对每个元素进行操作，返回该元素与指定参数的操作结果
        Integer reduce = stream2.reduce(0, Integer::sum);


        // 流类型转换
        Stream<String> stringStream = Stream.of("1", "2", "3", "4", "5");

        IntStream intStream1 = stringStream.mapToInt(Integer::parseInt);

        Stream<Integer> boxed = intStream1.boxed();


        // Collectors
        // 1. 聚合集合
        stringStream.collect(Collectors.toList());
        // 2. 分组
        Map<Integer, List<String>> collect1 = stringStream.collect(Collectors.groupingBy(String::length));
        Map<Boolean, List<String>> collect2 = stringStream.collect(Collectors.partitioningBy(e -> e.length() > 10));

        // 3. averaging 平均值
        integerStream.collect(Collectors.averagingDouble(e -> e));

        // 4. collectingAndThen
        Double collect3 =
            integerStream.collect(Collectors.collectingAndThen(Collectors.averagingDouble(e -> e), p -> p * 2));

        // 5. counting
        Long collect4 = integerStream.collect(Collectors.counting());
        // 等同于
        Long collect5 = integerStream.count();

        // 6. Collectors.mapping
        Long collect6 =
            integerStream.collect(Collectors.mapping(e -> e * 0.1, Collectors.summingLong(Double::longValue)));

        // 7. Collectors.joining 连接各元素
        stringStream.collect(Collectors.joining());
        stringStream.collect(Collectors.joining(","));
        stringStream.collect(Collectors.joining(",", "[", "]"));

        // 8. Collectors.summing

        // 9. Collectors.maxBy   / Collectors.minBy

        // 10. Collectors.summarizing 汇总 返回结果：DoubleSummaryStatistics
        DoubleSummaryStatistics collect7 = integerStream.collect(Collectors.summarizingDouble(e -> e));

        // 11. Collectors.partitioningBy 分区

        // 12. Collectors.groupingBy 分组

        // 13. Collectors.reducing

    }


}
